package dyyx.util;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

import javax.servlet.http.HttpServletRequest;

import com.alibaba.dubbo.common.utils.StringUtils;
import com.alibaba.dubbo.rpc.RpcContext;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;

import dyyx.HelloService;
import dyyx.TraceIdUtils;

public abstract class WebUtil {

	// private static final Logger LOG = Logger.getLogger(WebUtil.class);

	public static final String VERSION = "dubbo-hello-consumer-2019-11-08 15:00";

	public static final String TRUE = "true";
	public static final String FALSE = "false";

	public static final String TYPE = "type";
	public static final String NAME = "name";
	public static final String VALUE = "value";
	public static final String RESULT = "result";
	public static final String ERROR = "error";

	public static final String TYPE_STATUS = "status";

	public static final String TYPE_INFO = "info";

	public static final String TYPE_ECHO = "echo";
	public static final String TYPE_HELLO = "hello";
	public static final String TYPE_DUBBO_STATUS = "dubbo_status";

	
	public static final String TYPE_REMOTE_INFO = "remote_info";


	private static final Set<String> TYPES = new HashSet<String>();

	private static final AtomicLong seq = new AtomicLong(0);

	public static final Map<String, String> dataMap = new ConcurrentHashMap<String, String>();
	
	private static volatile HelloService service = null;


	static {
		TYPES.add(TYPE_STATUS);
		TYPES.add(TYPE_INFO);
		TYPES.add(TYPE_ECHO);
		TYPES.add(TYPE_REMOTE_INFO);
		TYPES.add(TYPE_HELLO);
		TYPES.add(TYPE_DUBBO_STATUS);

		


	}
	
	private static HelloService getService(){
		if(service!=null){
			return service;
		}
		return  getService_();
	}
	
    private static synchronized HelloService getService_(){
		if(service!=null){
			return service;
		}
		HelloService serviceTmp = WebAppContextUtil.getHelloService();
		service = serviceTmp;
		return service;
	}

	public static String toJsonString(Object obj) {
		if (obj == null) {
			return null;
		}
		return JSON.toJSONString(obj, SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.PrettyFormat,
				SerializerFeature.IgnoreErrorGetter);

	}

	public static Boolean getBoolean(String str) {
		if (TRUE.equals(str)) {
			return true;
		}
		if (FALSE.equals(str)) {
			return false;
		}

		return null;
	}

	public static boolean isBlank(String str) {
		if (str == null) {
			return true;
		}
		if (str.length() <= 0) {
			return true;
		}

		return false;
	}

	public static String get(HttpServletRequest request, String name) {
		if (request == null || name == null) {
			return null;
		}
		String str = request.getParameter(name);
		if (str != null) {
			str = str.trim();
		}
		return str;
	}

	public static int getInt(HttpServletRequest request, String name) {
		String str = get(request, name);
		return getInt(str);
	}

	public static long getLong(HttpServletRequest request, String name) {
		String str = get(request, name);
		return getLong(str);
	}

	public static int getInt(String str) {
		try {
			return Integer.parseInt(str);
		} catch (Throwable e) {
			return 0;
		}
	}

	public static long getLong(String str) {
		try {
			return Long.parseLong(str);
		} catch (Throwable e) {
			return 0;
		}
	}

	public static void run(HttpServletRequest request, Map<String, Object> context) throws Exception {
		String type = get(request, TYPE);
		if (type == null || type.length() <= 0) {
			type = TYPE_STATUS;
		}

		if (!TYPES.contains(type)) {
			context.put(ERROR, "type error");
			return;
		}

		context.put(TYPE, type);

		// echo
		if (TYPE_STATUS.equals(type)) {
			run_status(request, context);

		} else {

			try {
				String methodName = "run_" + type;
				Method method = WebUtil.class.getDeclaredMethod(methodName, HttpServletRequest.class, Map.class);
				method.setAccessible(true);
				method.invoke(null, request, context);
			} catch (Throwable e) {
				// e.printStackTrace();
				context.put(ERROR, e + "");
				context.put("errorList", CommUtil.getErrorInfo(e));
			}

		}

	}

	private static void run_status(HttpServletRequest request, Map<String, Object> context) {
		context.put(RESULT, RunStatusUtil.runStatus);

	}
	
	private static void run_dubbo_status(HttpServletRequest request, Map<String, Object> context) {
		context.put(RESULT, DubboStatusUtil.getStatus());

	}

	private static void run_info(HttpServletRequest request, Map<String, Object> context) throws Exception {
		// context.put(RESULT, RunStatusUtil.runStatus);

		Map<String, Object> data = new HashMap<String, Object>();

		data.put("version", VERSION);

		// data.put("config", ConfigUtil.getAllConfig());

		// data.put("appConfig", AppConfigUtil.getInfo());

		context.put(RESULT, data);
	}
	
	private static void run_remote_info(HttpServletRequest request, Map<String, Object> context) throws Exception {
		// context.put(RESULT, RunStatusUtil.runStatus);

		long start = System.currentTimeMillis();

		try {


			Map<String,Object> infomap = getService().getInfo();
			context.put(RESULT, infomap);

			long end = System.currentTimeMillis();
			long time = end - start;
			RunStatusUtil.logTime("getRemoteInfoTime", time);

		} catch (Throwable e) {

			context.put(ERROR, "getRemoteInfo_error_" + e);

			long end = System.currentTimeMillis();
			long time = end - start;
			RunStatusUtil.logTime("getRemoteInfoErrorTime", time);

			RunStatusUtil.logError("getRemoteInfoError", e);
		}


	}

	private static void run_echo(HttpServletRequest request, Map<String, Object> context) throws Exception {

		long start = System.currentTimeMillis();

		try {


			String result = getService().echo();
			context.put(RESULT, result);

			long end = System.currentTimeMillis();
			long time = end - start;
			RunStatusUtil.logTime("echoTime", time);

		} catch (Throwable e) {

			context.put(ERROR, "echo_error_" + e);

			long end = System.currentTimeMillis();
			long time = end - start;
			RunStatusUtil.logTime("echoErrorTime", time);

			RunStatusUtil.logError("runEchoError", e);
		}

	}
	
	private static void run_hello(HttpServletRequest request, Map<String, Object> context) throws Exception {

		String traceId = TraceIdUtils.genTraceId();
		RpcContext.getContext().setAttachment("traceId", traceId);
		long start = System.currentTimeMillis();

		try {
            String name = request.getParameter("name");
            if(StringUtils.isBlank(name)) {
            	name = "dyyx";
            }
            RpcContext rpcContext = RpcContext.getContext();
            rpcContext.getAttachments().put("name", name);
            
			context.put("attachment_name", rpcContext.getAttachments().get("name"));
			
			context.put("isConsumerSide", rpcContext.isConsumerSide());
			context.put("isProviderSide", rpcContext.isProviderSide());
			context.put("remoteAddressString", rpcContext.getRemoteAddressString());
			context.put("remotePort", rpcContext.getRemotePort());
			context.put("remoteHostName", rpcContext.getRemoteHostName());
			// context.put("application", RpcContext.getContext().getUrl().getParameter("application"));

			

			String result = getService().hello(name);
			
			String attachment_name_after_invoke = RpcContext.getContext().getAttachments().get("name");
			if(attachment_name_after_invoke==null) {
				attachment_name_after_invoke = "NULL";
			}
			context.put("attachment_name_after_invoke", attachment_name_after_invoke);

			
			
			context.put(RESULT, result);

			long end = System.currentTimeMillis();
			long time = end - start;
			RunStatusUtil.logTime("echoTime", time);

		} catch (Throwable e) {

			context.put(ERROR, "echo_error_" + e);

			long end = System.currentTimeMillis();
			long time = end - start;
			RunStatusUtil.logTime("echoErrorTime", time);

			RunStatusUtil.logError("runEchoError", e);
		}

	}

}
